'''
Created on Mar 23, 2011

@author: Christopher Nguyen
'''
import json

from django.http import HttpResponse
import gdata.books.service

import util


GBOOKS_MAX = 20 # Google limits max to 20
# input q or isbn, max/offset/indent
# output JSON from standards committee

API_RULESET = {
    'author': {
        'cond': lambda i: 'authors' in i,
        'cnvt': lambda i: i['authors']
    },
    'description': {
        'cond': lambda i: 'description' in i,
        'cnvt': lambda i: i['description']
    },
    'publisher': {
        'cond': lambda i: 'publishers' in i,
        'cnvt': lambda i: i['publishers']
    },
    'subject': {
        'cond': lambda i: 'subjects' in i,
        'cnvt': lambda i: i['subjects']
    },
    'title': {
        'cond': lambda i: 'title' in i,
        'cnvt': lambda i: i['title']
    },
    'isbn_10': {
        'cond': lambda i: len(extract_isbns(i['identifiers'], 10)) > 0,
        'cnvt': lambda i: extract_isbns(i['identifiers'], 10)[0]
    },
    'isbn_13': {
        'cond': lambda i: len(extract_isbns(i['identifiers'], 13)) > 0,
        'cnvt': lambda i: extract_isbns(i['identifiers'], 13)[0]
    }
}

def extract_isbns(identifiers, n):
    validator = getattr(util, 'valid_isbn_%d' % n)
    isbns = [y for (x,y) in identifiers
             if (x == 'ISBN') and
                len(y.replace('-', '')) == n and
                validator(y)]
    return isbns

def convert(entry):
    attr = util.convert(entry, API_RULESET)
    if len(attr) == 0:
        return None
    return {'type': 'book', 'attributes': attr}

def lookup(q, isbn=False, offset=1, max=0):
    if offset < 1: offset = 1
    if max <= 0: max = GBOOKS_MAX
    if isbn: q = 'isbn:%s' % q

    query = gdata.service.Query(text_query=q)
    service = gdata.books.service.BookService()
    data = service.search(q=query,
                          start_index=str(offset),
                          max_results=str(max))
    items = [convert(entry.to_dict()) for entry in data.entry]
    items = filter(lambda i: i is not None, items)
    return items

def search(request):
    # Extract optional arguments
    try:
        args = dict(request.GET.items())
        default = {'indent': None, 'max': 0, 'offset': 0}
        for o in args:
            if o in default:
                del default[o]
        args.update(default)
        for o in ['max', 'offset']: args[o] = int(args[o])
        if args['indent'] is not None:
            args['indent'] = int(args['indent'])

        q = args['isbn'] if 'isbn' in args else args['q']
        isbn = 'isbn' in args
        items = lookup(q=q,
                   isbn=isbn,
                   offset=args['offset'],
                   max=args['max'])
        output = json.dumps(items, indent = args['indent'])
        return HttpResponse(output, mimetype = 'application/json')
    except:
        return util.error(0)
